package com.simpleplayer.services;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import androidx.annotation.Nullable;

import com.google.common.net.HttpHeaders;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.NoRouteToHostException;
import java.net.ProtocolException;
import java.net.URL;

// 网络服务，完成向远程服务器请求数据的操作
public class NetWorkService {

    private static final String TAG = "NetWorkService";

    private static final int DEFAULT_CONNECTION_TIME_OUT = 3_000;
    private static final int DEFAULT_READ_TIME_OUT = 3_000;
    private static final String DEFAULT_REFERER = "";
    private static final String DEFAULT_USERAGENT = "Mozilla/5.0 (Linux; Android 11; M2011K2C) " +
            "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.86 Mobile Safari/537.36";
    private static final int MAX_REDIRECTS = 20;    // Same limit as okhttp.
    private static final int HTTP_STATUS_TEMPORARY_REDIRECT = 307;
    private static final int HTTP_STATUS_PERMANENT_REDIRECT = 308;

    /**
     * 建立一个 HttpURLConnection(支持重定向)
     */
    private static HttpURLConnection makeConnection(String url) throws IOException {
        int redirectCount = 0;
        URL pageURL = new URL(url);
        while (redirectCount++ <= MAX_REDIRECTS) {
            HttpURLConnection connection = makeConnection(pageURL);
            int responseCode = connection.getResponseCode();
            String location = connection.getHeaderField("Location");
            if (responseCode == HttpURLConnection.HTTP_MULT_CHOICE
                    || responseCode == HttpURLConnection.HTTP_MOVED_PERM
                    || responseCode == HttpURLConnection.HTTP_MOVED_TEMP
                    || responseCode == HttpURLConnection.HTTP_SEE_OTHER
                    || responseCode == HTTP_STATUS_TEMPORARY_REDIRECT
                    || responseCode == HTTP_STATUS_PERMANENT_REDIRECT) {
                connection.disconnect();
                pageURL = handleRedirect(pageURL, location);
            } else if (responseCode >= 200 && responseCode < 300) {
                return connection;
            } else {
                connection.disconnect();
                return null;
            }
        }

        // If we get here we've been redirected more times than are permitted.
        throw new NoRouteToHostException("Too many redirects: " + redirectCount);
    }

    /**
     * 构建一个HttpURLConnection.
     *  @param url 需要连接的url.
     * */
    private static HttpURLConnection makeConnection(URL url) throws IOException {
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        // 设置参数和默认头部
        connection.setRequestMethod("GET");
        connection.setConnectTimeout(DEFAULT_CONNECTION_TIME_OUT);
        connection.setReadTimeout(DEFAULT_READ_TIME_OUT);
        connection.setRequestProperty(HttpHeaders.REFERER, DEFAULT_REFERER);
        connection.setRequestProperty(HttpHeaders.USER_AGENT, DEFAULT_USERAGENT);
        connection.setRequestProperty(HttpHeaders.ACCEPT_ENCODING, "identity"); // 返回的数据编码
        connection.setInstanceFollowRedirects(true);

        connection.connect();
        return connection;
    }

    /**
     * 处理一次重定向.
     * @param originalUrl 原来的URL
     * @param location response 中的 "Location" 头部内容. 可能为 {@code null}.
     * @return 重定向后的URL.
     * @throws IOException If redirection isn't possible.
     */
    private static URL handleRedirect(URL originalUrl, @Nullable String location) throws IOException {
        if (location == null) {
            throw new ProtocolException("Null location redirect");
        }
        // Form the new url.
        URL url = new URL(originalUrl, location);
        // Check that the protocol of the new url is supported.
        String protocol = url.getProtocol();
        if (!"https".equals(protocol) && !"http".equals(protocol)) {
            throw new ProtocolException("Unsupported protocol redirect: " + protocol);
        }
        return url;
    }

    /**
     * 获取一张图片的 bitmap 数据
     * @param url 图片 url
     * @return 图片 bitmap，url无效或不是图像地址时返回 null
     */
    public static Bitmap getURLImage(String url) {
        Bitmap bmp = null;
        try {
            HttpURLConnection connection = makeConnection(url);
            if (connection != null) {
                bmp = BitmapFactory.decodeStream(connection.getInputStream());
                connection.disconnect();
            }
        } catch (Exception ex) {
            LogUtil.w(TAG, "occur exception when get image: " + url);
            ex.printStackTrace();
        }

        return bmp;
    }

    /**
     * 获取一个 url 对应的字符串内容
     * @return 远程服务器返回的字节流转化的字符串，出现异常时返回 null
     */
    public static String getURLContent(String url) {
        String content = null;
        try {
            HttpURLConnection connection = NetWorkService.makeConnection(url);
            if (connection != null) {
                //把二进制数据转化为byte字节数据
                BufferedReader br = new BufferedReader(
                        new InputStreamReader(connection.getInputStream()));
                StringBuilder sb = new StringBuilder();
                String line = null;
                while((line = br.readLine()) != null){
                    sb.append(line).append("\n");
                }
                content = sb.toString();
                connection.disconnect();
            }
        } catch (Exception ex) {
            LogUtil.w(TAG, "occur exception when get content: " + url);
            ex.printStackTrace();
        }

        return content;
    }


}
